<?php

namespace NorthernLights\JetBrainsLicensing;

use NorthernLights\JetBrainsLicensing\Exception\InvalidArgumentException;

/**
 * Class TicketProperties
 * @package NorthernLights\JetBrainsLicensing
 */
class TicketProperties
{
    /** @var  array */
    private $properties;

    /** @var string */
    private $toStringSeparator;

    /**
     * TicketProperties constructor.
     *
     * @param array $default
     * @param string|null $toStringSeparator
     */
    public function __construct(array $default = [], string $toStringSeparator = null)
    {
        $this->properties        = $default;
        $this->toStringSeparator = $toStringSeparator ?? chr(9);
    }

    /**
     * Builds a compatible tab separated string out of properties
     *
     * @return string
     */
    public function __toString(): string
    {
        return http_build_query($this->properties, '', $this->toStringSeparator);
    }

    /**
     * Set specified property
     *
     * @param string $name
     * @param string|int|float|bool $value
     *
     * @return TicketProperties
     */
    public function set(string $name, $value): self
    {
        if ($this->validateValue($value)) {
            throw new InvalidArgumentException(
                sprintf(
                    'Argument 2 cannot be of type %s',
                    gettype($value)
                )
            );
        }

        $this->properties[$name] = $value;

        return $this;
    }

    /**
     * Get specified property
     *
     * @param string $name
     *
     * @return string|int|float|bool|null
     */
    public function get(string $name)
    {
        return $this->properties[$name] ?? null;
    }

    /**
     * Get all stored properties
     *
     * @return array
     */
    public function getAll(): array
    {
        return $this->properties;
    }

    /**
     * Remove property
     *
     * @param string $name
     *
     * @return TicketProperties
     */
    public function remove(string $name): self
    {
        unset($this->properties[$name]);

        return $this;
    }

    /**
     * @param mixed $value
     *
     * @return bool
     */
    private function validateValue($value)
    {
        return ! (is_array($value) || is_object($value));
    }
}
